package com.example.demo.serviceImpl.report;

import com.example.demo.dao.report.*;
import com.example.demo.dao.task.TaskReportDao;
import com.example.demo.dao.user.WorkerReportDao;
import com.example.demo.po.bug.Bug;
import com.example.demo.po.report.Report;
import com.example.demo.po.report.SimilarReport;
import com.example.demo.po.user.User;
import com.example.demo.service.bug.BugService;
import com.example.demo.service.picture.PictureService;
import com.example.demo.service.remark.RemarkService;
import com.example.demo.service.report.ReportService;
import com.example.demo.service.task.TaskService;
import com.example.demo.service.user.UserService;
import com.example.demo.utils.Constant;
import com.example.demo.utils.UserHolder;
import com.example.demo.utils.similarity.StrSimilarity;
import com.example.demo.vo.bug.BugInfoVO;
import com.example.demo.vo.bug.BugVO;
import com.example.demo.vo.remark.RemarkVO;
import com.example.demo.vo.report.ReportInfoVO;
import com.example.demo.vo.report.ReportVO;
import com.example.demo.vo.ResultVO;
import com.example.demo.vo.report.SimilarReportVO;
import com.example.demo.vo.user.WorkerTaskVO;
import lombok.Data;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Service
public class ReportServiceImpl implements ReportService {
    @Resource
    TaskReportDao taskReportDao;
    @Resource
    WorkerReportDao workerReportDao;
    @Resource
    ReportDao reportDao;
    @Resource
    ReportBugDao reportBugDao;
    @Resource
    ReportRemarkDao reportRemarkDao;
    @Resource
    SimilarityDao similarityDao;
    @Resource
    ReportCoreportDao reportCoreportDao;
    @Resource
    PictureService pictureService;
    @Resource
    UserService userService;
    @Resource
    BugService bugService;
    @Resource
    TaskService taskService;
    @Resource
    RemarkService remarkService;


    @Override
    public ResultVO<Integer> getMyRid(int tid) {
        Integer uid = UserHolder.getUser().getUid();
        Integer rid = reportDao.selectReportByUserAndTask(uid, tid);
        return new ResultVO<>(1,"成功",rid);
    }

    @Override
    public ResultVO<ReportVO> getReportByRid(int rid) {
        return new ResultVO<>(1,"查询成功",reportDao.selectReportByRid(rid));
    }

    @Override
    public ResultVO<List<ReportVO>> getReportByTask(int tid,int pageNum) {
        if(taskService.getTaskById(tid)==null){
            return new ResultVO<List<ReportVO>>(-1,"任务不存在",null);
        }
        List<Report> reportIdS = taskReportDao.selectReportByTask(tid,pageNum,10);
        List<ReportVO> reportVOS=new ArrayList<>();
        for(Report reportId:reportIdS){
            reportVOS.add(new ReportVO(reportId));
        }
        int fullPageNum=(taskReportDao.selectReportByTask(tid,2,0).size()-1)/10+1;
        return new ResultVO<List<ReportVO>>(1,pageNum+"/"+fullPageNum,reportVOS);
    }

    @Override
    public ResultVO<ReportVO> getReportByWorkerTask(String username, int tid) {
        if(taskService.getTaskById(tid)==null){
            return new ResultVO<ReportVO>(-1,"任务不存在",null);
        }
        if(userService.getUserByName(username)==null){
            return new ResultVO<ReportVO>(-1,"用户不存在",null);
        }
        User user = userService.getUserByName(username);
        return new ResultVO<ReportVO>(1,"查询成功",new ReportVO(workerReportDao.selectReportByWorkerTask(user.getUid(),tid)));
    }

    //用于暂存相似度数据
     @Data
     class Sim{
        private int targetRid;
        private double sim;

         public Sim(int targetRid, double sim) {
             this.targetRid = targetRid;
             this.sim = sim;
         }
     }

    @Override
    public ResultVO<ReportInfoVO> uploadReport(ReportInfoVO reportInfoVO) {
//        System.out.println(reportInfoVO.getBugList().get(0).getPictures().get(0));
        String username=reportInfoVO.getUsername();
        int tid=reportInfoVO.getTid();
        List<BugInfoVO> bugInfoVOS=reportInfoVO.getBugList();
        ReportVO reportVO=new ReportVO();

        //计算相似度，超过预设值就返回
        ArrayList<Sim> simTemp=new ArrayList<>();
        List<Report> allReports = taskReportDao.selectReportByTask(tid,1,0);
        //储存超出预设值的报告
        ReportInfoVO simReportInfoVO = new ReportInfoVO();
        simReportInfoVO.setSimilarity(new ArrayList<>());
        for(Report report : allReports){
            int targetRid = report.getRid();
            List<Bug> bugs = reportBugDao.selectBugByReport(targetRid);
            double sim = StrSimilarity.reportSimilarity(bugInfoVOS, bugs);
            if(sim> Constant.MAX_ACCEPT_SIMILARITY){
                SimilarReportVO similarReportVO=new SimilarReportVO();
                similarReportVO.setRid(targetRid);
                similarReportVO.setSimilarity(sim);
                simReportInfoVO.getSimilarity().add(similarReportVO);
            }
            simTemp.add(new Sim(targetRid,sim));
        }
        if(!simReportInfoVO.getSimilarity().isEmpty()){
            return new ResultVO<>(-2,"报告相似度过高",simReportInfoVO);
        }
        //相似度合格，插入数据库
        reportDao.insertReport(reportVO);
        int rid=reportVO.getRid();
        for(Sim sim:simTemp){
            similarityDao.insertSim(rid,sim.getTargetRid(), sim.getSim());
        }

        taskReportDao.insertTaskReport(tid,rid);
        workerReportDao.insertWorkerReport(userService.getUserByName(username).getUid(),rid);
        for (BugInfoVO bugInfoVO:bugInfoVOS){
            BugVO bugVO=new BugVO(bugInfoVO);
            userService.updateDevice(username,bugInfoVO.getDeviceInfo());
            bugService.insertBug(bugVO);
            int bid=bugVO.getBid();
            reportBugDao.insertReportBug(rid,bid);
            List<String> pictureNames=bugInfoVO.getPictures();
            for(String pictureName:pictureNames){
                int pid=pictureService.getPictureByAddress(pictureName).getPid();
                pictureService.insertBugPicture(bid,pid);
            }

        }
        userService.updateAbility(username,taskService.getDifficultyByTid(tid));
        WorkerTaskVO workerTaskVO=new WorkerTaskVO(tid,username,2);
        userService.setTakeTaskState(workerTaskVO);
        return new ResultVO<>(1,"成功",reportInfoVO);
    }

    @Override
    public ResultVO<List<RemarkVO>> getRemarkByRid(int rid,int pageNum) {
        List<RemarkVO> res = remarkService.getRemarkByRid(rid,pageNum);
        int fullPageNum=(reportRemarkDao.selectRemarkByRid(rid,1, Constant.NO_PAGE_SIZE).size()-1)/10+1;
        if(res.size()==0)
            return new ResultVO<List<RemarkVO>>(-1,"没有数据",res);
        return new ResultVO<List<RemarkVO>>(1,pageNum+"/"+fullPageNum,res);
    }

    @Override
    public ResultVO<List<ReportVO>> getRemarkableReportListByTaskId(int tid, int uid,int pageNum) {
        List<Report> res= reportRemarkDao.selectRemarkableReportListByTaskId(tid,uid,pageNum,10);
        if(res.size()==0){
            return new ResultVO<>(-1,"查询失败，没有可打分的报告",new ArrayList<ReportVO>());
        }
        List<ReportVO> reportVOS=new ArrayList<>();
        for(Report report:res){
            reportVOS.add(new ReportVO(report));
        }
        int fullPageNum=(reportRemarkDao.selectRemarkableReportListByTaskId(tid,uid,1,0).size()-1)/10+1;
        return new ResultVO<>(1,pageNum+"/"+fullPageNum,reportVOS);
    }

    @Override
    public ResultVO<List<SimilarReportVO>> getReportWithSimilarity(int tid, int uid) {
        List<SimilarReport> similarReportS = reportDao.selectReportWithSimilarity(tid, uid,1,Constant.NO_PAGE_SIZE);
        List<SimilarReportVO> res=new ArrayList<>();
        if(similarReportS.size()==0){
            return new ResultVO<>(-1,"查询失败，没有相似报告",new ArrayList<SimilarReportVO>());
        }
        for(SimilarReport similarReport : similarReportS){
            //相似度比较低的报告不展示
            if(similarReport.getSim()<Constant.MAX_SHOW_SIMILARITY)
                continue;
            SimilarReportVO similarReportVO=new SimilarReportVO(similarReport);
            int base=similarReport.getBaseRid();
            int rid1=similarReport.getRid1();
            int rid2=similarReport.getRid2();
            similarReportVO.setRid(rid1==base?rid2:rid1);
            res.add(similarReportVO);
        }
        int fullPageNum=(reportDao.selectReportWithSimilarity(tid, uid,1,0).size()-1)/10+1;
        return new ResultVO<>(1,"成功",res);
    }

    @Override
    public ResultVO<List<ReportVO>> getReportWithScore(int tid,int uid) {
        List<Report> reportList= taskReportDao.selectReportWithScore(tid,uid,1,Constant.DEFAULT_PAGE_SIZE);
        if(reportList.size()==0){
            return new ResultVO<>(-1,"未查询到报告",new ArrayList<ReportVO>());
        }
        List<ReportVO> res=new ArrayList<>();
        for(Report report:reportList){
            if(report.getAverageScore()<Constant.LOW_QUALITY_FLAG)
                res.add(new ReportVO(report));
        }
        int fullPageNum=(taskReportDao.selectReportWithScore(tid,uid,1,0).size()-1)/10+1;
        return new ResultVO<>(1,"成功",res);
    }

    @Override
    public int getCoreportNumByRid(int rid) {
        return reportCoreportDao.selectCoreportCountByRid(rid);
    }

    @Override
    public int getSimilarityNumByRid(int rid,int min,int max){
        double minDouble=(double)min/100;
        double maxDouble=(double)max/100;
        return similarityDao.selectSimCountByRid(rid,minDouble,maxDouble);
    }

    @Override
    public int getRecentReportNumByUser(String username) {
        return reportDao.selectRecentReportNumByUser(username);
    }

    @Override
    public int updateAvgScore(int rid, int score,double active) {
        return reportDao.updateAvgScore(rid,score, active);
    }

    //获取报告的相似报告
    @Override
    public ResultVO<List<ReportVO>> getSimilarityReportListByRid(int rid,int min,int max,int pageNum){
        double minDouble=(double)min/100;
        double maxDouble=(double)max/100;
        List<Report> res= similarityDao.selectSimReportListByRid(rid,minDouble,maxDouble,pageNum,10);
        if(res.size()==0){
            return new ResultVO<>(-1,"查询失败，没有相似报告",new ArrayList<ReportVO>());
        }
        List<ReportVO> reportVOS=new ArrayList<>();
        for(Report report:res){
            reportVOS.add(new ReportVO(report));
        }
        int fullPageNum=(similarityDao.selectSimReportListByRid(rid,minDouble,maxDouble,1,0).size()-1)/10+1;
        return new ResultVO<>(1,pageNum+"/"+fullPageNum,reportVOS);
    }

    @Override
    public int getBugNumByReport(int rid) {
        return reportBugDao.selectBugByReport(rid).size();
    }


    @Override
    public String getAllBugByRid(int rid) {
        String AllBugInfo="";
        List<String> bugInfoS=reportBugDao.selectBugInfo(rid);
        for(String bugInfo: bugInfoS){
            AllBugInfo=AllBugInfo+bugInfo;
        }
        return AllBugInfo;
    }
}
